#include <QWidget>
#include <QDebug>
#include "ConfigItem.h"


ConfigItem::ConfigItem()
{
    connect(this, &ConfigItem::itemEdited, this, &ConfigItem::onItemEdited);
    connect(this, &ConfigItem::widgetEdited, this, &ConfigItem::onWidgetEdited);
}

void ConfigItem::relate(QWidget *w)
{
    if (w)
    {
        w->setObjectName(this->objectName());
        this->updateItem(w, UpdateOption::WidgetContent);
        relatedWidgets.insert(w);
        connect(w, &QObject::destroyed, this, &ConfigItem::onWidgetDestroyed);
    }
}

QWidget *ConfigItem::createRelatedWidget()
{
    auto w = createWidget();
    relate(w);
    return w;
}

QWidget *ConfigItem::createRelatedWidget(WidgetStyle s)
{
    auto w = createWidget(s);
    relate(w);
    return w;
}

ConfigItem::WidgetStyle ConfigItem::getWidgetStyle()
{
    return m_widgetStyle;
}

void ConfigItem::setWidgetStyle(ConfigItem::WidgetStyle s)
{
    m_widgetStyle = s;
}

void ConfigItem::updateItem(QWidget *widget, UpdateOption option)
{
    blockSignals(true);
    update(widget, option);
    blockSignals(false);
}

QWidget *ConfigItem::createWidget()
{
    return createWidget(m_widgetStyle);
}


void ConfigItem::onItemEdited()
{
    for (auto w : relatedWidgets)
    {
        this->updateItem(w, UpdateOption::WidgetContent);
    }
}

void ConfigItem::onWidgetDestroyed(QObject *obj)
{
    relatedWidgets.remove(qobject_cast<QWidget*>(obj));
    // qInfo() << "removed " << obj;
}



void ConfigItem::onWidgetEdited(QWidget *w)
{
    /* 术语定义：把 createWidget() 返回的对象叫做 configWidget
       对于 ItemInt ，它们的信号发送者 QSpinBox 是 configWidget 控件本身
       对于 ItemEnum ，它们的信号发送者 QRadioButton 是 configWidget 的子控件
       由此得出 sender 可能为 configWidget，也能为 configWidget 的子控件。
       但更新时用到的是 item->update(configWidget)
       所以这里做一个调整
    */
    if (w && w->objectName() == this->objectName())
    {
        this->updateItem(w, UpdateOption::Item);
        emit itemEdited();
    }
    else if (w && w->parentWidget() && w->parentWidget()->objectName() == this->objectName())
    {
        this->updateItem(w->parentWidget(), UpdateOption::Item);
        emit itemEdited();
    }
}

void ConfigItem::onWidgetEditedWrapper()
{
    auto w = qobject_cast<QWidget*>(sender());
    if (w)
    {
        emit widgetEdited(w, QPrivateSignal());
    }
}

QDataStream &operator<<(QDataStream &stream, const ConfigItem &item)
{
    item.writeToData(stream);
    return stream;
}

QDataStream &operator>>(QDataStream &stream, ConfigItem &item)
{
    item.readFromData(stream);
    return stream;
}
